<!DOCTYPE html>
<html lang="en-us">
  <head>

    <meta http-equiv="content-type" content="text/html; charset=utf-8">
    
<meta charset="UTF-8">
<title>Join datatype | Elasticsearch Guide [7.7] | Elastic</title>
<link rel="home" href="index.html" title="Elasticsearch Guide [7.7]">
<link rel="up" href="mapping-types.html" title="Field datatypes">
<link rel="prev" href="ip.html" title="IP datatype">
<link rel="next" href="keyword.html" title="Keyword datatype">
<meta name="DC.type" content="Learn/Docs/Elasticsearch/Reference/7.7">
<meta name="DC.subject" content="Elasticsearch">
<meta name="DC.identifier" content="7.7">
<meta name="robots" content="noindex,nofollow">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <script src="https://cdn.optimizely.com/js/18132920325.js"></script>
    <link rel="apple-touch-icon" sizes="57x57" href="/apple-icon-57x57.png">
    <link rel="apple-touch-icon" sizes="60x60" href="/apple-icon-60x60.png">
    <link rel="apple-touch-icon" sizes="72x72" href="/apple-icon-72x72.png">
    <link rel="apple-touch-icon" sizes="76x76" href="/apple-icon-76x76.png">
    <link rel="apple-touch-icon" sizes="114x114" href="/apple-icon-114x114.png">
    <link rel="apple-touch-icon" sizes="120x120" href="/apple-icon-120x120.png">
    <link rel="apple-touch-icon" sizes="144x144" href="/apple-icon-144x144.png">
    <link rel="apple-touch-icon" sizes="152x152" href="/apple-icon-152x152.png">
    <link rel="apple-touch-icon" sizes="180x180" href="/apple-icon-180x180.png">
    <link rel="icon" type="image/png" href="/favicon-32x32.png" sizes="32x32">
    <link rel="icon" type="image/png" href="/android-chrome-192x192.png" sizes="192x192">
    <link rel="icon" type="image/png" href="/favicon-96x96.png" sizes="96x96">
    <link rel="icon" type="image/png" href="/favicon-16x16.png" sizes="16x16">
    <link rel="manifest" href="/manifest.json">
    <meta name="apple-mobile-web-app-title" content="Elastic">
    <meta name="application-name" content="Elastic">
    <meta name="msapplication-TileColor" content="#ffffff">
    <meta name="msapplication-TileImage" content="/mstile-144x144.png">
    <meta name="theme-color" content="#ffffff">
    <meta name="naver-site-verification" content="936882c1853b701b3cef3721758d80535413dbfd">
    <meta name="yandex-verification" content="d8a47e95d0972434">
    <meta name="localized" content="true">
    <meta name="st:robots" content="follow,index">
    <meta property="og:image" content="https://www.elastic.co/static/images/elastic-logo-200.png">
    <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
    <link rel="icon" href="/favicon.ico" type="image/x-icon">
    <link rel="apple-touch-icon-precomposed" sizes="64x64" href="/favicon_64x64_16bit.png">
    <link rel="apple-touch-icon-precomposed" sizes="32x32" href="/favicon_32x32.png">
    <link rel="apple-touch-icon-precomposed" sizes="16x16" href="/favicon_16x16.png">
    <!-- Give IE8 a fighting chance -->
    <!--[if lt IE 9]>
    <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
    <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
    <![endif]-->
    <link rel="stylesheet" type="text/css" href="/guide/static/styles.css">
  </head>

  <!--© 2015-2021 Elasticsearch B.V. Copying, publishing and/or distributing without written permission is strictly prohibited.-->

  <body>
    <!-- Google Tag Manager -->
    <script>dataLayer = [];</script><noscript><iframe src="//www.googletagmanager.com/ns.html?id=GTM-58RLH5" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
    <script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= '//www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); })(window,document,'script','dataLayer','GTM-58RLH5');</script>
    <!-- End Google Tag Manager -->

    <!-- Global site tag (gtag.js) - Google Analytics -->
    <script async src="https://www.googletagmanager.com/gtag/js?id=UA-12395217-16"></script>
    <script>
      window.dataLayer = window.dataLayer || [];
      function gtag(){dataLayer.push(arguments);}
      gtag('js', new Date());
      gtag('config', 'UA-12395217-16');
    </script>

    <!--BEGIN QUALTRICS WEBSITE FEEDBACK SNIPPET-->
    <script type="text/javascript">
      (function(){var g=function(e,h,f,g){
      this.get=function(a){for(var a=a+"=",c=document.cookie.split(";"),b=0,e=c.length;b<e;b++){for(var d=c[b];" "==d.charAt(0);)d=d.substring(1,d.length);if(0==d.indexOf(a))return d.substring(a.length,d.length)}return null};
      this.set=function(a,c){var b="",b=new Date;b.setTime(b.getTime()+6048E5);b="; expires="+b.toGMTString();document.cookie=a+"="+c+b+"; path=/; "};
      this.check=function(){var a=this.get(f);if(a)a=a.split(":");else if(100!=e)"v"==h&&(e=Math.random()>=e/100?0:100),a=[h,e,0],this.set(f,a.join(":"));else return!0;var c=a[1];if(100==c)return!0;switch(a[0]){case "v":return!1;case "r":return c=a[2]%Math.floor(100/c),a[2]++,this.set(f,a.join(":")),!c}return!0};
      this.go=function(){if(this.check()){var a=document.createElement("script");a.type="text/javascript";a.src=g;document.body&&document.body.appendChild(a)}};
      this.start=function(){var a=this;window.addEventListener?window.addEventListener("load",function(){a.go()},!1):window.attachEvent&&window.attachEvent("onload",function(){a.go()})}};
      try{(new g(100,"r","QSI_S_ZN_emkP0oSe9Qrn7kF","https://znemkp0ose9qrn7kf-elastic.siteintercept.qualtrics.com/WRSiteInterceptEngine/?Q_ZID=ZN_emkP0oSe9Qrn7kF")).start()}catch(i){}})();
    </script><div id="ZN_emkP0oSe9Qrn7kF"><!--DO NOT REMOVE-CONTENTS PLACED HERE--></div>
    <!--END WEBSITE FEEDBACK SNIPPET-->

    <div id="elastic-nav" style="display:none;"></div>
    <script src="https://www.elastic.co/elastic-nav.js"></script>

    <!-- Subnav -->
    <div>
      <div>
        <div class="tertiary-nav d-none d-md-block">
          <div class="container">
            <div class="p-t-b-15 d-flex justify-content-between nav-container">
              <div class="breadcrum-wrapper"><span><a href="/guide/" style="font-size: 14px; font-weight: 600; color: #000;">Docs</a></span></div>
            </div>
          </div>
        </div>
      </div>
    </div>

    <div class="main-container">
      <section id="content">
        <div class="content-wrapper">

          <section id="guide" lang="en">
            <div class="container">
              <div class="row">
                <div class="col-xs-12 col-sm-8 col-md-8 guide-section">
                  <!-- start body -->
                  <div class="page_header">
<strong>IMPORTANT</strong>: No additional bug fixes or documentation updates
will be released for this version. For the latest information, see the
<a href="../current/index.html">current release documentation</a>.
</div>
<div id="content">
<div class="breadcrumbs">
<span class="breadcrumb-link"><a href="index.html">Elasticsearch Guide [7.7]</a></span>
»
<span class="breadcrumb-link"><a href="mapping.html">Mapping</a></span>
»
<span class="breadcrumb-link"><a href="mapping-types.html">Field datatypes</a></span>
»
<span class="breadcrumb-node">Join datatype</span>
</div>
<div class="navheader">
<span class="prev">
<a href="ip.html">« IP datatype</a>
</span>
<span class="next">
<a href="keyword.html">Keyword datatype »</a>
</span>
</div>
<div class="section">
<div class="titlepage"><div><div>
<h2 class="title">
<a id="parent-join"></a>Join datatype<a class="edit_me edit_me_private" rel="nofollow" title="Editing on GitHub is available to Elastic" href="https://github.com/elastic/elasticsearch/edit/7.7/docs/reference/mapping/types/parent-join.asciidoc">edit</a>
</h2>
</div></div></div>

<p>The <code class="literal">join</code> datatype is a special field that creates
parent/child relation within documents of the same index.
The <code class="literal">relations</code> section defines a set of possible relations within the documents,
each relation being a parent name and a child name.
A parent/child relation can be defined as follows:</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">PUT my_index
{
  "mappings": {
    "properties": {
      "my_id": {
        "type": "keyword"
      },
      "my_join_field": { <a id="CO297-1"></a><i class="conum" data-value="1"></i>
        "type": "join",
        "relations": {
          "question": "answer" <a id="CO297-2"></a><i class="conum" data-value="2"></i>
        }
      }
    }
  }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/659.console"></div>
<div class="calloutlist">
<table border="0" summary="Callout list">
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO297-1"><i class="conum" data-value="1"></i></a></p>
</td>
<td align="left" valign="top">
<p>The name for the field</p>
</td>
</tr>
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO297-2"><i class="conum" data-value="2"></i></a></p>
</td>
<td align="left" valign="top">
<p>Defines a single relation where <code class="literal">question</code> is parent of <code class="literal">answer</code>.</p>
</td>
</tr>
</table>
</div>
<p>To index a document with a join, the name of the relation and the optional parent
of the document must be provided in the <code class="literal">source</code>.
For instance the following example creates two <code class="literal">parent</code> documents in the <code class="literal">question</code> context:</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">PUT my_index/_doc/1?refresh
{
  "my_id": "1",
  "text": "This is a question",
  "my_join_field": {
    "name": "question" <a id="CO298-1"></a><i class="conum" data-value="1"></i>
  }
}

PUT my_index/_doc/2?refresh
{
  "my_id": "2",
  "text": "This is another question",
  "my_join_field": {
    "name": "question"
  }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/660.console"></div>
<div class="calloutlist">
<table border="0" summary="Callout list">
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO298-1"><i class="conum" data-value="1"></i></a></p>
</td>
<td align="left" valign="top">
<p>This document is a <code class="literal">question</code> document.</p>
</td>
</tr>
</table>
</div>
<p>When indexing parent documents, you can choose to specify just the name of the relation
as a shortcut instead of encapsulating it in the normal object notation:</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">PUT my_index/_doc/1?refresh
{
  "my_id": "1",
  "text": "This is a question",
  "my_join_field": "question" <a id="CO299-1"></a><i class="conum" data-value="1"></i>
}

PUT my_index/_doc/2?refresh
{
  "my_id": "2",
  "text": "This is another question",
  "my_join_field": "question"
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/661.console"></div>
<div class="calloutlist">
<table border="0" summary="Callout list">
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO299-1"><i class="conum" data-value="1"></i></a></p>
</td>
<td align="left" valign="top">
<p>Simpler notation for a parent document just uses the relation name.</p>
</td>
</tr>
</table>
</div>
<p>When indexing a child, the name of the relation as well as the parent id of the document
must be added in the <code class="literal">_source</code>.</p>
<div class="warning admon">
<div class="icon"></div>
<div class="admon_content">
<p>It is required to index the lineage of a parent in the same shard so you must
always route child documents using their greater parent id.</p>
</div>
</div>
<p>For instance the following example shows how to index two <code class="literal">child</code> documents:</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">PUT my_index/_doc/3?routing=1&amp;refresh <a id="CO300-1"></a><i class="conum" data-value="1"></i>
{
  "my_id": "3",
  "text": "This is an answer",
  "my_join_field": {
    "name": "answer", <a id="CO300-2"></a><i class="conum" data-value="2"></i>
    "parent": "1" <a id="CO300-3"></a><i class="conum" data-value="3"></i>
  }
}

PUT my_index/_doc/4?routing=1&amp;refresh
{
  "my_id": "4",
  "text": "This is another answer",
  "my_join_field": {
    "name": "answer",
    "parent": "1"
  }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/662.console"></div>
<div class="calloutlist">
<table border="0" summary="Callout list">
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO300-1"><i class="conum" data-value="1"></i></a></p>
</td>
<td align="left" valign="top">
<p>The routing value is mandatory because parent and child documents must be indexed on the same shard</p>
</td>
</tr>
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO300-2"><i class="conum" data-value="2"></i></a></p>
</td>
<td align="left" valign="top">
<p><code class="literal">answer</code> is the name of the join for this document</p>
</td>
</tr>
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO300-3"><i class="conum" data-value="3"></i></a></p>
</td>
<td align="left" valign="top">
<p>The parent id of this child document</p>
</td>
</tr>
</table>
</div>
<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="_parent_join_and_performance"></a>Parent-join and performance.<a class="edit_me edit_me_private" rel="nofollow" title="Editing on GitHub is available to Elastic" href="https://github.com/elastic/elasticsearch/edit/7.7/docs/reference/mapping/types/parent-join.asciidoc">edit</a>
</h3>
</div></div></div>
<p>The join field shouldn’t be used like joins in a relation database. In Elasticsearch the key to good performance
is to de-normalize your data into documents. Each join field, <code class="literal">has_child</code> or <code class="literal">has_parent</code> query adds a
significant tax to your query performance.</p>
<p>The only case where the join field makes sense is if your data contains a one-to-many relationship where
one entity significantly outnumbers the other entity. An example of such case is a use case with products
and offers for these products. In the case that offers significantly outnumbers the number of products then
it makes sense to model the product as parent document and the offer as child document.</p>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="_parent_join_restrictions"></a>Parent-join restrictions<a class="edit_me edit_me_private" rel="nofollow" title="Editing on GitHub is available to Elastic" href="https://github.com/elastic/elasticsearch/edit/7.7/docs/reference/mapping/types/parent-join.asciidoc">edit</a>
</h3>
</div></div></div>
<div class="ulist itemizedlist">
<ul class="itemizedlist">
<li class="listitem">
Only one <code class="literal">join</code> field mapping is allowed per index.
</li>
<li class="listitem">
Parent and child documents must be indexed on the same shard.
This means that the same <code class="literal">routing</code> value needs to be provided when
<a class="xref" href="docs-get.html" title="Get API">getting</a>, <a class="xref" href="docs-delete.html" title="Delete API">deleting</a>, or <a class="xref" href="docs-update.html" title="Update API">updating</a>
a child document.
</li>
<li class="listitem">
An element can have multiple children but only one parent.
</li>
<li class="listitem">
It is possible to add a new relation to an existing <code class="literal">join</code> field.
</li>
<li class="listitem">
It is also possible to add a child to an existing element
but only if the element is already a parent.
</li>
</ul>
</div>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="_searching_with_parent_join"></a>Searching with parent-join<a class="edit_me edit_me_private" rel="nofollow" title="Editing on GitHub is available to Elastic" href="https://github.com/elastic/elasticsearch/edit/7.7/docs/reference/mapping/types/parent-join.asciidoc">edit</a>
</h3>
</div></div></div>
<p>The parent-join creates one field to index the name of the relation
within the document (<code class="literal">my_parent</code>, <code class="literal">my_child</code>, …​).</p>
<p>It also creates one field per parent/child relation.
The name of this field is the name of the <code class="literal">join</code> field followed by <code class="literal">#</code> and the
name of the parent in the relation.
So for instance for the <code class="literal">my_parent</code> → [<code class="literal">my_child</code>, <code class="literal">another_child</code>] relation,
the <code class="literal">join</code> field creates an additional field named <code class="literal">my_join_field#my_parent</code>.</p>
<p>This field contains the parent <code class="literal">_id</code> that the document links to
if the document is a child (<code class="literal">my_child</code> or <code class="literal">another_child</code>) and the <code class="literal">_id</code> of
document if it’s a parent (<code class="literal">my_parent</code>).</p>
<p>When searching an index that contains a <code class="literal">join</code> field, these two fields are always
returned in the search response:</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET my_index/_search
{
  "query": {
    "match_all": {}
  },
  "sort": ["my_id"]
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/663.console"></div>
<p>Will return:</p>
<div class="pre_wrapper lang-console-result">
<pre class="programlisting prettyprint lang-console-result">{
    ...,
    "hits": {
        "total" : {
            "value": 4,
            "relation": "eq"
        },
        "max_score": null,
        "hits": [
            {
                "_index": "my_index",
                "_type": "_doc",
                "_id": "1",
                "_score": null,
                "_source": {
                    "my_id": "1",
                    "text": "This is a question",
                    "my_join_field": "question" <a id="CO301-1"></a><i class="conum" data-value="1"></i>
                },
                "sort": [
                    "1"
                ]
            },
            {
                "_index": "my_index",
                "_type": "_doc",
                "_id": "2",
                "_score": null,
                "_source": {
                    "my_id": "2",
                    "text": "This is another question",
                    "my_join_field": "question" <a id="CO301-2"></a><i class="conum" data-value="2"></i>
                },
                "sort": [
                    "2"
                ]
            },
            {
                "_index": "my_index",
                "_type": "_doc",
                "_id": "3",
                "_score": null,
                "_routing": "1",
                "_source": {
                    "my_id": "3",
                    "text": "This is an answer",
                    "my_join_field": {
                        "name": "answer", <a id="CO301-3"></a><i class="conum" data-value="3"></i>
                        "parent": "1"  <a id="CO301-4"></a><i class="conum" data-value="4"></i>
                    }
                },
                "sort": [
                    "3"
                ]
            },
            {
                "_index": "my_index",
                "_type": "_doc",
                "_id": "4",
                "_score": null,
                "_routing": "1",
                "_source": {
                    "my_id": "4",
                    "text": "This is another answer",
                    "my_join_field": {
                        "name": "answer",
                        "parent": "1"
                    }
                },
                "sort": [
                    "4"
                ]
            }
        ]
    }
}</pre>
</div>
<div class="calloutlist">
<table border="0" summary="Callout list">
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO301-1"><i class="conum" data-value="1"></i></a></p>
</td>
<td align="left" valign="top">
<p>This document belongs to the <code class="literal">question</code> join</p>
</td>
</tr>
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO301-2"><i class="conum" data-value="2"></i></a></p>
</td>
<td align="left" valign="top">
<p>This document belongs to the <code class="literal">question</code> join</p>
</td>
</tr>
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO301-3"><i class="conum" data-value="3"></i></a></p>
</td>
<td align="left" valign="top">
<p>This document belongs to the <code class="literal">answer</code> join</p>
</td>
</tr>
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO301-4"><i class="conum" data-value="4"></i></a></p>
</td>
<td align="left" valign="top">
<p>The linked parent id for the child document</p>
</td>
</tr>
</table>
</div>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="_parent_join_queries_and_aggregations"></a>Parent-join queries and aggregations<a class="edit_me edit_me_private" rel="nofollow" title="Editing on GitHub is available to Elastic" href="https://github.com/elastic/elasticsearch/edit/7.7/docs/reference/mapping/types/parent-join.asciidoc">edit</a>
</h3>
</div></div></div>
<p>See the <a class="xref" href="query-dsl-has-child-query.html" title="Has child query"><code class="literal">has_child</code></a> and
<a class="xref" href="query-dsl-has-parent-query.html" title="Has parent query"><code class="literal">has_parent</code></a> queries,
the <a class="xref" href="search-aggregations-bucket-children-aggregation.html" title="Children Aggregation"><code class="literal">children</code></a> aggregation,
and <a class="xref" href="search-request-body.html#parent-child-inner-hits" title="Parent/child inner hits">inner hits</a> for more information.</p>
<p>The value of the <code class="literal">join</code> field is accessible in aggregations
and scripts, and may be queried with the
<a class="xref" href="query-dsl-parent-id-query.html" title="Parent ID query"><code class="literal">parent_id</code> query</a>:</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET my_index/_search
{
  "query": {
    "parent_id": { <a id="CO302-1"></a><i class="conum" data-value="1"></i>
      "type": "answer",
      "id": "1"
    }
  },
  "aggs": {
    "parents": {
      "terms": {
        "field": "my_join_field#question", <a id="CO302-2"></a><i class="conum" data-value="2"></i>
        "size": 10
      }
    }
  },
  "script_fields": {
    "parent": {
      "script": {
         "source": "doc['my_join_field#question']" <a id="CO302-3"></a><i class="conum" data-value="3"></i>
      }
    }
  }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/664.console"></div>
<div class="calloutlist">
<table border="0" summary="Callout list">
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO302-1"><i class="conum" data-value="1"></i></a></p>
</td>
<td align="left" valign="top">
<p>Querying the <code class="literal">parent id</code> field (also see the <a class="xref" href="query-dsl-has-parent-query.html" title="Has parent query"><code class="literal">has_parent</code> query</a> and the <a class="xref" href="query-dsl-has-child-query.html" title="Has child query"><code class="literal">has_child</code> query</a>)</p>
</td>
</tr>
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO302-2"><i class="conum" data-value="2"></i></a></p>
</td>
<td align="left" valign="top">
<p>Aggregating on the <code class="literal">parent id</code> field (also see the <a class="xref" href="search-aggregations-bucket-children-aggregation.html" title="Children Aggregation"><code class="literal">children</code></a> aggregation)</p>
</td>
</tr>
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO302-3"><i class="conum" data-value="3"></i></a></p>
</td>
<td align="left" valign="top">
<p>Accessing the parent id` field in scripts</p>
</td>
</tr>
</table>
</div>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="_global_ordinals"></a>Global ordinals<a class="edit_me edit_me_private" rel="nofollow" title="Editing on GitHub is available to Elastic" href="https://github.com/elastic/elasticsearch/edit/7.7/docs/reference/mapping/types/parent-join.asciidoc">edit</a>
</h3>
</div></div></div>
<p>The <code class="literal">join</code> field uses <a class="xref" href="eager-global-ordinals.html" title="eager_global_ordinals">global ordinals</a> to speed up joins.
Global ordinals need to be rebuilt after any change to a shard. The more
parent id values are stored in a shard, the longer it takes to rebuild the
global ordinals for the <code class="literal">join</code> field.</p>
<p>Global ordinals, by default, are built eagerly: if the index has changed,
global ordinals for the <code class="literal">join</code> field will be rebuilt as part of the refresh.
This can add significant time to the refresh. However most of the times this is the
right trade-off, otherwise global ordinals are rebuilt when the first parent-join
query or aggregation is used. This can introduce a significant latency spike for
your users and usually this is worse as multiple global ordinals for the <code class="literal">join</code>
field may be attempt rebuilt within a single refresh interval when many writes
are occurring.</p>
<p>When the <code class="literal">join</code> field is used infrequently and writes occur frequently it may
make sense to disable eager loading:</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">PUT my_index
{
  "mappings": {
    "properties": {
      "my_join_field": {
        "type": "join",
        "relations": {
           "question": "answer"
        },
        "eager_global_ordinals": false
      }
    }
  }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/665.console"></div>
<p>The amount of heap used by global ordinals can be checked per parent relation
as follows:</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console"># Per-index
GET _stats/fielddata?human&amp;fields=my_join_field#question

# Per-node per-index
GET _nodes/stats/indices/fielddata?human&amp;fields=my_join_field#question</pre>
</div>
<div class="console_widget" data-snippet="snippets/666.console"></div>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="_multiple_children_per_parent"></a>Multiple children per parent<a class="edit_me edit_me_private" rel="nofollow" title="Editing on GitHub is available to Elastic" href="https://github.com/elastic/elasticsearch/edit/7.7/docs/reference/mapping/types/parent-join.asciidoc">edit</a>
</h3>
</div></div></div>
<p>It is also possible to define multiple children for a single parent:</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">PUT my_index
{
  "mappings": {
    "properties": {
      "my_join_field": {
        "type": "join",
        "relations": {
          "question": ["answer", "comment"]  <a id="CO303-1"></a><i class="conum" data-value="1"></i>
        }
      }
    }
  }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/667.console"></div>
<div class="calloutlist">
<table border="0" summary="Callout list">
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO303-1"><i class="conum" data-value="1"></i></a></p>
</td>
<td align="left" valign="top">
<p><code class="literal">question</code> is parent of <code class="literal">answer</code> and <code class="literal">comment</code>.</p>
</td>
</tr>
</table>
</div>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="_multiple_levels_of_parent_join"></a>Multiple levels of parent join<a class="edit_me edit_me_private" rel="nofollow" title="Editing on GitHub is available to Elastic" href="https://github.com/elastic/elasticsearch/edit/7.7/docs/reference/mapping/types/parent-join.asciidoc">edit</a>
</h3>
</div></div></div>
<div class="warning admon">
<div class="icon"></div>
<div class="admon_content">
<p>Using multiple levels of relations to replicate a relational model is not recommended.
Each level of relation adds an overhead at query time in terms of memory and computation.
You should de-normalize your data if you care about performance.</p>
</div>
</div>
<p>Multiple levels of parent/child:</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">PUT my_index
{
  "mappings": {
    "properties": {
      "my_join_field": {
        "type": "join",
        "relations": {
          "question": ["answer", "comment"],  <a id="CO304-1"></a><i class="conum" data-value="1"></i>
          "answer": "vote" <a id="CO304-2"></a><i class="conum" data-value="2"></i>
        }
      }
    }
  }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/668.console"></div>
<div class="calloutlist">
<table border="0" summary="Callout list">
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO304-1"><i class="conum" data-value="1"></i></a></p>
</td>
<td align="left" valign="top">
<p><code class="literal">question</code> is parent of <code class="literal">answer</code> and <code class="literal">comment</code></p>
</td>
</tr>
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO304-2"><i class="conum" data-value="2"></i></a></p>
</td>
<td align="left" valign="top">
<p><code class="literal">answer</code> is parent of <code class="literal">vote</code></p>
</td>
</tr>
</table>
</div>
<p>The mapping above represents the following tree:</p>
<pre class="literallayout">   question
    /    \
   /      \
comment  answer
           |
           |
          vote</pre>

<p>Indexing a grandchild document requires a <code class="literal">routing</code> value equals
to the grand-parent (the greater parent of the lineage):</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">PUT my_index/_doc/3?routing=1&amp;refresh <a id="CO305-1"></a><i class="conum" data-value="1"></i>
{
  "text": "This is a vote",
  "my_join_field": {
    "name": "vote",
    "parent": "2" <a id="CO305-2"></a><i class="conum" data-value="2"></i>
  }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/669.console"></div>
<div class="calloutlist">
<table border="0" summary="Callout list">
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO305-1"><i class="conum" data-value="1"></i></a></p>
</td>
<td align="left" valign="top">
<p>This child document must be on the same shard than its grand-parent and parent</p>
</td>
</tr>
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO305-2"><i class="conum" data-value="2"></i></a></p>
</td>
<td align="left" valign="top">
<p>The parent id of this document (must points to an <code class="literal">answer</code> document)</p>
</td>
</tr>
</table>
</div>
</div>

</div>
<div class="navfooter">
<span class="prev">
<a href="ip.html">« IP datatype</a>
</span>
<span class="next">
<a href="keyword.html">Keyword datatype »</a>
</span>
</div>
</div>

                  <!-- end body -->
                </div>
                <div class="col-xs-12 col-sm-4 col-md-4" id="right_col">
                  <div id="rtpcontainer" style="display: block;">
                    <div class="mktg-promo">
                      <h3>Most Popular</h3>
                      <ul class="icons">
                        <li class="icon-elasticsearch-white"><a href="https://www.elastic.co/webinars/getting-started-elasticsearch?baymax=default&amp;elektra=docs&amp;storm=top-video">Get Started with Elasticsearch: Video</a></li>
                        <li class="icon-kibana-white"><a href="https://www.elastic.co/webinars/getting-started-kibana?baymax=default&amp;elektra=docs&amp;storm=top-video">Intro to Kibana: Video</a></li>
                        <li class="icon-logstash-white"><a href="https://www.elastic.co/webinars/introduction-elk-stack?baymax=default&amp;elektra=docs&amp;storm=top-video">ELK for Logs &amp; Metrics: Video</a></li>
                      </ul>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </section>

        </div>


<div id="elastic-footer"></div>
<script src="https://www.elastic.co/elastic-footer.js"></script>
<!-- Footer Section end-->

      </section>
    </div>

<script src="/guide/static/jquery.js"></script>
<script type="text/javascript" src="/guide/static/docs.js"></script>
<script type="text/javascript">
  window.initial_state = {}</script>
  </body>
</html>
